package config

import play.api.libs.json.{JsObject, Json}
import utils.Utils

import scala.collection.mutable
import scala.language.implicitConversions

trait Blast extends MyFile {

  implicit class getDataByTable(path: String) {
    val xlsx: mutable.Buffer[String] = (path + "/table.xls").readLines

    val line: mutable.Buffer[Array[String]] = xlsx.tail.map(_.split("\t").map(_.trim))

    val sort1: mutable.Buffer[String] = (path + "/seq.fa").readLines.filter(_.startsWith(">")).map { x =>
      x.tail.split(" ").head
    }

    def getBarData: mutable.Buffer[JsObject] = {
      val le = (Global.path + "/length.txt").readLines

      val heightM = le.map(_.split("\t")).map(x => x.head.trim -> x.tail).toMap

      val blastMap = line.map { xlx =>
        (xlx(5), xlx(11).split("-").last, xlx(11).split("-").head, xlx(13), xlx(14))
      }.groupBy(_._1).map { x =>
        (x._1, x._2.groupBy(_._2).map { y =>
          (y._1, y._2.map { z =>
            val chr = z._2 + "-" + z._3
            val range = z._4 + "-" + z._5
            val length = Math.abs(z._5.toInt - z._4.toInt)
            val title = "Chr : " + chr + "\nRange : " + range + "\nLength : " + length
            //染色体/起始坐标/标题/比对到的基因名/长度
            (z._3, z._4, title, z._3 + "-" + z._2, length)
          })
        })
      }

      val barMap = line.map(x => (x(5), x(11))).distinct

      val sort = line.map(x => (x(5), x(11).split("-").last)).distinct

      sort.map(_._1).distinct.zipWithIndex.flatMap { x =>
        sort.filter(_._1 == x._1).zipWithIndex.map { y =>
          val bar = y._1._2
          val height = heightM(bar).map { z =>
            val c = z.split(":")
            Json.obj("key" -> c.head, "value" -> c.last)
          }

          val barIndex = barMap.filter(_._1 == x._1).map(_._2).distinct.zipWithIndex

          val sortMax = blastMap(x._1)(bar).sortBy(_._5).reverse

          val gen = sortMax.drop(3).map { g =>
            Json.obj("name" -> x._1, "key" -> g._1,
              "value" -> g._2, "title" -> g._3, "hitid" -> ((x._2 + 1) + "-" + (barIndex.filter(_._1 == g._4).head._2 + 1)))
          }
          val max3 = sortMax.take(3).map { g =>
            Json.obj("name" -> x._1, "key" -> g._1,
              "value" -> g._2, "title" -> g._3, "hitid" -> ((x._2 + 1) + "-" + (barIndex.filter(_._1 == g._4).head._2 + 1)))
          }

          Json.obj("seq" -> (sort1.indexOf(x._1) + 1), "bar" -> bar, "height" -> height, "gen" -> gen, "max3" -> max3)
        }
      }
    }


    def getSyntenyData: Array[JsObject] = {
      line.map { xlx =>
        (xlx(5), xlx(11), xlx(7), xlx(8), xlx(9), xlx(13), xlx(14))
      }.groupBy(_._1).flatMap { x =>
        val sort2 = line.filter(_ (5) == x._1).map(_ (11)).distinct
        x._2.groupBy(_._2).map { y =>
          val aName = x._1
          val aMin = 1
          val aMax = y._2.head._3.toInt
          val rectA = y._2.map { z =>
            Array("", z._4, z._5)
          }

          val bName = y._1
          val bRange = y._2.flatMap(z => Array(z._6.toInt, z._7.toInt))
          val bMin = bRange.min
          val bMax = bRange.max
          val rectB = y._2.map { z =>
            Array("", z._6, z._7)
          }

          val relate = y._2.zipWithIndex.map(z => Array(z._2 + 1, z._2 + 1))

          val data = Json.obj("A" -> Json.obj("name" -> aName, "min" -> aMin, "max" -> aMax, "seqType" -> "Query", "rect" -> rectA),
            "B" -> Json.obj("name" -> bName, "min" -> bMin, "max" -> bMax, "seqType" -> "Subject", "rect" -> rectB))

          val i1 = sort1.indexOf(x._1) + 1
          val i2 = sort2.indexOf(y._1) + 1
          Json.obj("data" -> data, "relate" -> relate, "index" -> (i1 + "-" + i2))
        }
      }.toArray

    }


  }

  val scriptHtml: String =
    """
      |<script>
      |	$(function () {
      |			    $("footer:first").remove()
      |        $("#content").css("margin","0")
      |       $(".linkheader>a").each(function () {
      |				   var text=$(this).text()
      |				   $(this).replaceWith("<span style='color: #222222;'>"+text+"</span>")
      |			   })
      |
      |      $("tr").each(function () {
      |         var a=$(this).find("td>a:last")
      |					var text=a.text()
      |					a.replaceWith("<span style='color: #222222;'>"+text+"</span>")
      |				})
      |
      |       $("p.titleinfo>a").each(function () {
      |				   var text=$(this).text()
      |				   $(this).replaceWith("<span style='color: #606060;'>"+text+"</span>")
      |			   })
      |
      |       $(".param:eq(1)").parent().hide()
      |       $(".linkheader").hide()
      |
      |			})
      |</script>
    """.stripMargin
}
